package util;

import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpUtil {

	private final Integer OVERTIME = 60 * 1000;
	private final Integer RETRYTIMES = 3;
	
	public String ssl(String urlPath) throws Exception {
		return ssl(urlPath, null);
	}

	public String ssl(String urlPath, Map<String,String> paramsMap) throws Exception {
		return ssl(urlPath, paramsMap, OVERTIME);
	}
	
	public String ssl(String urlPath, Map<String,String> paramsMap,Integer overTime) throws Exception {
		// 相信自己的CA和所有自签名的证书
		SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
			// 信任所有
			public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				return true;
			}
		}).build();
		// 只允许使用TLSv1协议
		SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).setRetryHandler(new DefaultHttpRequestRetryHandler(RETRYTIMES, true)).build();
		HttpPost httpPost = new HttpPost(urlPath);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(overTime).setConnectTimeout(overTime).setConnectionRequestTimeout(overTime).build();
		httpPost.setConfig(requestConfig);
		List<BasicNameValuePair> formparams = new ArrayList<BasicNameValuePair>();
		if (paramsMap != null) {
			for(Map.Entry<String, String> entry: paramsMap.entrySet()){
				formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		httpPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
		CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
		HttpEntity httpEntity = httpResponse.getEntity();
		Header ceheader = httpEntity.getContentEncoding();
		if (ceheader != null) {
			for (HeaderElement element : ceheader.getElements()) {
				if ("gzip".equalsIgnoreCase(element.getName())) {
					httpEntity = new GzipDecompressingEntity(httpResponse.getEntity());
					break;
				}
			}
		}
		String result = null;
		if (httpEntity != null) {
			result = EntityUtils.toString(httpEntity, "UTF-8");
		}
		httpResponse.close();
		httpClient.close();
		return result;
	}
	
	public String post(String urlPath) throws Exception {
		return post(urlPath, null);
	}
	
	public String post(String urlPath, Map<String,String> paramsMap) throws Exception {
		return post(urlPath, paramsMap, OVERTIME);
	}

	public String post(String urlPath, Map<String,String> paramsMap,Integer overTime) throws Exception {
		CloseableHttpClient httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(RETRYTIMES, true)).build();
		HttpPost httpPost = new HttpPost(urlPath);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(overTime).setConnectTimeout(overTime).setConnectionRequestTimeout(overTime).build();// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		List<BasicNameValuePair> formparams = new ArrayList<BasicNameValuePair>();
		if (paramsMap != null) {
			for(Map.Entry<String, String> entry: paramsMap.entrySet()){
				formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		httpPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
		CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
		HttpEntity httpEntity = httpResponse.getEntity();
		Header ceheader = httpEntity.getContentEncoding();
		if (ceheader != null) {
			for (HeaderElement element : ceheader.getElements()) {
				if ("gzip".equalsIgnoreCase(element.getName())) {
					httpEntity = new GzipDecompressingEntity(httpResponse.getEntity());
					break;
				}
			}
		}
		String result = null;
		if (httpEntity != null) {
			result = EntityUtils.toString(httpEntity, "UTF-8");
		}
		httpResponse.close();
		httpClient.close();
		return result;
	}
	
	public String redirect(String urlPath) throws Exception {
		return redirect(urlPath, null);
	}
	
	public String redirect(String urlPath, Map<String,String> paramsMap) throws Exception {
		return redirect(urlPath, paramsMap, OVERTIME);
	}

	public String redirect(String urlPath, Map<String,String> paramsMap,Integer overTime) throws Exception {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpPost httpPost = new HttpPost(urlPath);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(overTime).setConnectTimeout(overTime).setConnectionRequestTimeout(overTime).build();// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		List<BasicNameValuePair> formparams = new ArrayList<BasicNameValuePair>();
		if (paramsMap != null) {
			for(Map.Entry<String, String> entry: paramsMap.entrySet()){
				formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		httpPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
		CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
		URL redirectUrl = new URL(httpResponse.getHeaders("location")[0].getValue());
		String result = redirectUrl.getQuery();
		httpResponse.close();
		httpClient.close();
		return result;
	}
	
	public String get(String urlPath) throws Exception {
		return get(urlPath, null);
	}

	public String get(String urlPath, Map<String,String> paramsMap) throws Exception {
		return get(urlPath, paramsMap, OVERTIME);
	}
	
	public String get(String urlPath, Map<String,String> paramsMap,Integer overTime) throws Exception {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpGet httpGet = new HttpGet(urlPath);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(overTime).setConnectTimeout(overTime).setConnectionRequestTimeout(overTime).build();// 设置请求和传输超时时间
		httpGet.setConfig(requestConfig);
		CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
		HttpEntity httpEntity = httpResponse.getEntity();
		Header ceheader = httpEntity.getContentEncoding();
		if (ceheader != null) {
			for (HeaderElement element : ceheader.getElements()) {
				if ("gzip".equalsIgnoreCase(element.getName())) {
					httpEntity = new GzipDecompressingEntity(httpResponse.getEntity());
					break;
				}
			}
		}
		String result = null;
		if (httpEntity != null) {
			result = EntityUtils.toString(httpEntity, "UTF-8");
		}
		httpResponse.close();
		httpClient.close();
		return result;
	}
	
	public String json(String urlPath) throws Exception {
		return json(urlPath, "{}");
	}
	
	public String json(String urlPath, String jsonParam) throws Exception {
		return json(urlPath, jsonParam, OVERTIME);
	}

	public String json(String urlPath, String jsonParam,Integer overTime) throws Exception {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpPost httpPost = new HttpPost(urlPath);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(overTime).setConnectTimeout(overTime).setConnectionRequestTimeout(overTime).build();// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
		httpPost.setEntity(new StringEntity(jsonParam, ContentType.create("application/json", Consts.UTF_8)));
		CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
		HttpEntity httpEntity = httpResponse.getEntity();
		String result = null;
		if (httpEntity != null) {
			result = EntityUtils.toString(httpEntity, "UTF-8");
		}
		httpResponse.close();
		httpClient.close();
		return result;

	}


}